package com.yisin.ssh2;

import java.io.File;
import java.util.ArrayList;

import com.yisin.ssh2.csharp.Timer;
import com.yisin.ssh2.csharp.Timer.ElapsedEventArgs;
import com.yisin.ssh2.csharp.Timer.ElapsedEventHandler;
import com.yisin.ssh2.jsch.ChannelSftp;
import com.yisin.ssh2.jsch.SftpException;
import com.yisin.ssh2.jsch.SftpProgressMonitor;

public class Sftp extends SshTransferProtocolBase {

	private MyProgressMonitor m_monitor;
	private boolean cancelled = false;

	public Sftp(String sftpHost, String user, String password) {
		super(sftpHost, user, password);
		Init();
	}

	public Sftp(String sftpHost, String user) {
		super(sftpHost, user);
		Init();
	}

	private void Init() {
		m_monitor = new MyProgressMonitor(this);
	}

	protected String getChannelType() {
		return "sftp";
	}

	private ChannelSftp getSftpChannel() {
		return (ChannelSftp) m_channel;
	}

	public void Cancel() {
		cancelled = true;
	}

	// Get

	public void Get(String fromFilePath) throws SftpException {
		Get(fromFilePath, ".");
	}

	public void Get(String[] fromFilePaths) throws SftpException {
		for (int i = 0; i < fromFilePaths.length; i++) {
			Get(fromFilePaths[i]);
		}
	}

	public void Get(String[] fromFilePaths, String toDirPath) throws SftpException {
		for (int i = 0; i < fromFilePaths.length; i++) {
			Get(fromFilePaths[i], toDirPath);
		}
	}

	public void Get(String fromFilePath, String toFilePath) throws SftpException {
		cancelled = false;
		getSftpChannel().get(fromFilePath, toFilePath, m_monitor, ChannelSftp.OVERWRITE);
	}

	// Put

	public void Put(String fromFilePath) throws SftpException {
		Put(fromFilePath, ".");
	}

	public void Put(String[] fromFilePaths) throws SftpException {
		for (int i = 0; i < fromFilePaths.length; i++) {
			Put(fromFilePaths[i]);
		}
	}

	public void Put(String[] fromFilePaths, String toDirPath) throws SftpException {
		for (int i = 0; i < fromFilePaths.length; i++) {
			Put(fromFilePaths[i], toDirPath);
		}
	}

	public void Put(String fromFilePath, String toFilePath) throws SftpException {
		cancelled = false;
		getSftpChannel().put(fromFilePath, toFilePath, m_monitor, ChannelSftp.OVERWRITE);
	}

	// MkDir
	public void Mkdir(String directory) throws SftpException {
		getSftpChannel().mkdir(directory);
	}

	// Ls
	public ArrayList<String> GetFileList(String path) throws SftpException {
		ArrayList<String> list = new ArrayList<String>();
		ChannelSftp.LsEntry entry = null;
		for (Object obj : getSftpChannel().ls(path)) {
			entry = (ChannelSftp.LsEntry) obj;
			list.add(entry.getFilename());
		}
		return list;
	}

	private class MyProgressMonitor implements SftpProgressMonitor {
		private long transferred = 0;
		private long total = 0;
		private int elapsed = -1;
		private Sftp m_sftp;
		private String src;
		private String dest;

		Timer timer;

		public MyProgressMonitor(Sftp sftp) {
			m_sftp = sftp;
		}

		public void init(int op, String src, String dest, long max) {
			this.src = src;
			this.dest = dest;
			this.elapsed = 0;
			this.total = max;

			timer = new Timer(1000);
			timer.Start();
			timer.Elapsed(new ElapsedEventHandler(this, "timerElapsed"));

			String note;
			if (op == GET) {
				note = "Downloading " + new File(src).getName() + "...";
			} else {
				note = "Uploading " + new File(src).getName() + "...";
			}
			m_sftp.SendStartMessage(src, dest, (int) total, note);
		}

		public boolean count(long c) {
			this.transferred += c;
			String note = ("Transfering... [Elapsed time: " + elapsed + "]");
			m_sftp.SendProgressMessage(src, dest, (int) transferred, (int) total, note);
			return !m_sftp.cancelled;
		}

		public void end() {
			timer.Stop();
			timer.Dispose();
			String note = ("Done in " + elapsed + " seconds!");
			m_sftp.SendEndMessage(src, dest, (int) transferred, (int) total, note);
			transferred = 0;
			total = 0;
			elapsed = -1;
			src = null;
			dest = null;
		}

		public void timerElapsed(Object sender, ElapsedEventArgs e) {
			this.elapsed++;
		}
	}
}
